# -*- coding: utf-8 -*-
#
# Copyright 2009 Vanderbilt University
# 
# Licensed under the Apache License, Version 2.0 (the "License"); 
# you may not use this file except in compliance with the License. 
# You may obtain a copy of the License at 
# 
#     http://www.apache.org/licenses/LICENSE-2.0 
# 
# Unless required by applicable law or agreed to in writing, software 
# distributed under the License is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
# See the License for the specific language governing permissions and 
# limitations under the License. 

"""Plugin that tests the number of graphs that each edge exists in. 

.. moduleauthor:: John Paulett <john.paulett -at- vanderbilt.edu>
"""
from __future__ import division
from collections import defaultdict
from hornet.event import GraphsReady
from hornet.file import write_csv
from hornet.plugin import Plugin, log
from hornet.util import count_unique, accumulate, dict_apply
import hornet.network
import logging

logger = logging.getLogger(__name__)

class EdgeAge(Plugin):
    """For the set of graphs provided to 
    :meth:`hornet.contrib.RulesExistanceLength.notify`, find out the number of
    graphs that each rule exists in.
    """
    def accepted_events(self):
        return GraphsReady
    
    @log
    def notify(self, event):
        write_csv(self.output('%s.csv' % self.id), 
                  edge_ages(event.data))

def edge_ages(graphs):
    """Compute the distribution of rules existing for a given number
    of weeks. Returns a 2D list of the results.
    """
    ages = calculate_ages(graphs)
    ratios = existence_ratios(ages)
    cdf = accumulate(ratios)
    
    result = []
    for length, ratio in ratios.iteritems():
        result.append([length, ratio, cdf[length]])
    result.sort(lambda x, y: cmp(x[0], y[0]))
    return result
    
def calculate_ages(graphs):
    """Tasks a list of graphs and returns a dictionary keyed by the edges
    with values of the number of graphs that edge appeared in.
    
    >>> from hornet.network import create_directed_graph, add_edge, Node
    >>> g, h = create_directed_graph(), create_directed_graph()
    >>> a, b = Node('a'), Node('b')
    >>> e = add_edge(g, a, b)
    >>> e = add_edge(g, b, a)
    >>> e = add_edge(h, a, b)
        
    >>> result = calculate_ages([g, h])
    >>> result[(a, b)]
    2
    >>> result[(b, a)]
    1
    """
    ages = defaultdict(int)
    for graph in graphs:
        for edge in graph.edges_iter(data=True):
            ages[edge[0:2]] += 1
    return dict(ages)

def existence_ratios(ages):
    """Find the percent of edges that exist for each length."""
    counts = count_unique(ages.itervalues())
    total = len(ages)
    ratios = dict_apply(counts, lambda v: v / total)
    return ratios
    

